/**
 * \file traducteur_message.c
 * \author H4201
 */

/* MODULES USED */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#include "traducteur_message.h"
#include "../interface/messqueue.h"

/*EXPORTED FUNCTIONS*/

/**
 * Transforme le message décrit par la structure message 
 * en une chaine de caractères
 * @param[in] message Le message à sérialiser
 * @return La chaîne de caractères créée à partir du message,
 * <tt>NULL</tt> si le message est invalide 
 */
char * serialiser_message(message_t message) {
    char * texte = NULL;
    int i, n;
    int nb_ecrits;
    int nb_params = nb_params_message(message.type);
    if (nb_params != -1) {
        /* on considère qu'un entier aura une longueur 
        jusqu'à 10 caractères plus un espace. */
        texte = calloc(((nb_params + 1) * 11), sizeof(char));
        nb_ecrits = sprintf(texte, "%ld", message.type);
        for (i=0; i<nb_params; i++) {
            n = sprintf(&texte[nb_ecrits], " %d", message.params[i]);
            nb_ecrits += n;
        }
        sprintf(&texte[nb_ecrits], "\n");
    }
    return texte;
}

/**
 * Traduit le message texte en une structure message.
 * @param[in] message_texte Le texte à désérialiser
 * @return Le message obtenu à partir du texte.
 * Si le texte ne décrit pas un message valide,
 * le message retourné sera de type -1.
 */
message_t deserialiser_message(char * message_texte) {
    int i = 0, lu;
    char *token, *copie_message, *a_liberer, *endptr;
    message_t message = {-1, {0}};
    
    a_liberer = copie_message = strdup(message_texte);
    
    token = strsep(&copie_message, " ");
    message.type = strtol(token, &endptr, 10);
    
    if (token == endptr) {
        message.type = -1;
        return message;
    }
    
    while ((token = strsep(&copie_message, " ")) != NULL) {
        lu = strtol(token, &endptr, 10);
        if (token == endptr) {
            message.type = -1;
            return message;
        }
        message.params[i] = lu;
        i++;
    }
    
    if (i != nb_params_message(message.type)) {
        message.type = -1;
        return message;
    }
    
    free(a_liberer);
    return message;
}

/**
 * Indique si deux messages sont égaux
 * @param[in] m1 L'un des messages à comparer
 * @param[in] m2 L'autre message à comparer
 * @return true/1 s'ils sont égaux, false/0 sinon.
 */
bool messages_egaux(message_t m1, message_t m2) {
    bool egaux = false;
    int i, nb_params;
    
    egaux = (m1.type == m2.type);
    
    nb_params = nb_params_message(m1.type);
    
    for (i=0; i<nb_params; i++) {
        if (m1.params[i] != m2.params[i]) {
            return false;
        }
    }
    return egaux;
}

/**
 * Retourne le nombre de paramètres d'un message selon son type
 * @param[in] type Le type du message dont on souhaite connaître
 * le nombre de paramètres
 * @return Le nombre de paramètres pour ce type de message.
 * -1 pour un type de message inexistant.
 */
int nb_params_message(int type) {
    switch (type) {
        case AU:        
        case ERRPIECE:
        case ERRCARTON:
        case ERRIMPR:
        case ERRDEFECT:
        case ERRFILE:
        case ERRPALETTE:
        case ERREMBAL:
        case ERRRETRAIT:
        case ARRET:
        case ARRDEG:
        case REPARERR:
        case REPRNORM:
        case REPRSUPP:
        case STOPLOT:
            return 0;
            break;

        case INIT:
            return 13;
            break;
        
        case GO:
            return 1;
            break;
        
        case IMPRIMER:
            return 6;
            break;

        case EMPALETTER:
        case STOCKER:
        case DEMRETRAIT:
        case STOCKOK:
        case RETRAITOK:
            return 3;
            break;
        
        case FINLOT:
            return 2;
            break;
        
        default:
            return -1;
    }
}
